<template>
  <div class="comp-filter-column-selector" :class="layout">
    <template v-if="value && value.length > 0">
      <div
        v-for="(item,i) in (Array.isArray(value)? value : [value])"
        :key="i"
        class="selet-item-box"
      >
        <div class="select-item" :class="checkIfShowStep(i) ? 'fix' : ''">
          <a-select
            :value="value[i] ? value[i].value : undefined"
            :disabled="disabled"
            :size="size"
            :dropdown-match-select-width="false"
            style="width: 100%;"
            :style="{
              maxWidth: '135px',
            }"
            allow-clear
            @change="
              (value) => {
                onChange(value, i, true)
              }
            "
          >
            <template v-if="checkIsGraphOptions(options)">
              <a-select-opt-group
                v-if="options.nodeColumns && options.nodeColumns.length > 0"
              >
                <span slot="label">节点字段</span>
                <a-select-option
                  v-for="(op, k) in options.nodeColumns"
                  :key="k"
                  :value="op.value"
                  :disabled="checkIsDisabled(op, op.value)"
                  >{{ op.label }}
                </a-select-option>
              </a-select-opt-group>

              <a-select-opt-group
                v-if="options.linkColumns && options.linkColumns.length > 0"
              >
                <span slot="label">关系字段</span>
                <a-select-option
                  v-for="(op, j) in options.linkColumns"
                  :key="`${j}__`"
                  :value="op.value"
                  :disabled="checkIsDisabled(op, op.value)"
                  >{{ op.label }}
                </a-select-option>
              </a-select-opt-group>
            </template>
            <template v-else-if="options && options.length > 0">
              <a-select-option
                v-for="(op, j) in options"
                :key="j"
                :size="size"
                :value="op.value"
                :disabled="checkIsDisabled(op, op.value)"
              >
                {{ op.label }}
              </a-select-option>
            </template>
          </a-select>
          <a-icon
            class="btn btn-add"
            title="添加"
            :class="{
              disabled: addBtnDisabled() || disabled,
            }"
            type="plus"
            @click="
              () => {
                if (!(value && value.length === options.length)) {
                  addItem(i)
                }
              }
            "
          />
          <a-icon
            class="btn btn-delete"
            title="删除"
            :class="{ disabled: (value && value.length == 1) || disabled }"
            type="minus"
            @click="
              () => {
                if (!(value && value.length == 1)) {
                  delteItem(i)
                }
              }
            "
          />
        </div>
        <div v-if="checkIfShowStep(i)" class="number-step-box">
          <span class="label">
            幅度调整单位
          </span>
          <a-input-number
            class="step"
            size="small"
            :min="1"
            :max="100"
            :precision="0"
            :step="0.5"
            :value="value[i].step"
            @change="
              (val) => {
                onStepChange(val, i)
              }
            "
          ></a-input-number>
          %
        </div>
      </div>
    </template>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { isArray, cloneDeep } from 'lodash'

interface KeyValueStore {
  [key: string]: any
}

const defaultValue = { value: '', type: 'string', step: 1 }

@Component
export default class MultipleSelect extends Vue {
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  disabled!: boolean
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  isSortable!: boolean
  @Prop({
    type: Array,
  })
  value!: Array<any>
  @Prop({
    type: Object,
    default() {
      return {}
    },
  })
  formData!: object

  @Prop({
    type: [Array, Object],
    default() {
      return []
    },
  })
  options!: any

  @Prop({
    type: String,
    default() {
      return 'small'
    },
  })
  size!: string

  @Prop({
    type: String,
    default() {
      return 'vertical' // horizontal | vertical
    },
  })
  layout!: string

  // 只有外部传入的value变化时才有响应，内部改变不响应，所以存一份内部拷贝innerValue
  private innerValue: Array<any> = []
  @Watch('value', { immediate: true })
  private onValueChange(newValue: Array<any>) {
    this.innerValue = newValue
  }

  /** 步进更改 */
  onStepChange(value: number, index: number) {
    const valueSet = cloneDeep(this.value)
    valueSet[index].step = value
    this.$emit('input', valueSet)
    this.$emit('change', valueSet)
  }

  checkIsDisabled(op: any, opValue: any) {
    return (
      op.disabled || !!this.innerValue.find((item) => item.value === opValue)
    )
  }

  addBtnDisabled() {
    const { options = {} as any } = this
    return this.checkIsGraphOptions(options)
      ? this.innerValue.length ===
          (options.nodeColumns || []).length +
            (options.linkColumns || []).length
      : this.innerValue.length >= options.length
  }

  get valueKeys() {
    /* eslint-disable */
    return this.innerValue.reduce((rec: Array<string>, item: KeyValueStore) => {
      const rec_ = item.value !== '' ? [...rec, item.value] : rec
      return rec_
    }, [])
  }

  get usedKeys(): Array<string> {
    /* eslint-disable */
    const result: Array<string> = isArray((this.formData as any).valueKey)
      ? (this.formData as any).valueKey.reduce(
          (rec: Array<string>, item: KeyValueStore) => {
            const rec_: Array<string> =
              item.value !== '' ? [...rec, item.value] : rec
            return rec_
          },
          []
        )
      : (this.formData as any).valueKey
      ? [(this.formData as any).valueKey]
      : []
    if ((this.formData as any).labelKey !== '') {
      result.push((this.formData as any).labelKey)
    }
    if ((this.formData as any).groupBy !== '') {
      result.push((this.formData as any).groupBy)
    }
    return result
  }
  checkIsGraphOptions(options: any) {
    return options.nodeColumns !== undefined
  }
  addItem(index: number) {
    if (this.addBtnDisabled() || this.disabled) {
      return
    }
    const value = cloneDeep(this.value)
    value.splice(index + 1, 0, cloneDeep(defaultValue))
    this.innerValue = value
    this.$emit('input', value)
    this.$emit('change', value)
  }
  delteItem(index: number) {
    if (this.value.length <= 1) {
      return
    }
    this.value.splice(index, 1)
    const value = cloneDeep(this.value)
    this.innerValue = value
    this.$emit('input', value)
    this.$emit('change', value)
  }
  onChange(_value: any, index: number, isColumn?: boolean) {
    const valueSet = cloneDeep(this.value)
    const value = _value === undefined ? '' : _value
    const filter = this.value.filter((item) => item === value)
    if (filter.length > 1) {
      valueSet[index] = cloneDeep(defaultValue)
    }
    valueSet[index].value = value
    if ([undefined, null, ''].includes(valueSet[index].value)) {
      valueSet[index].value.step = 1
    }
    if (isColumn) {
      if (this.checkIsGraphOptions(this.options)) {
        const find =
          ((this.options || {}) as any).nodeColumns?.find(
            (n: any) => n.value === value
          ) ||
          ((this.options || {}) as any).linkColumns?.find(
            (n: any) => n.value === value
          )
        valueSet[index] = {
          ...valueSet[index],
          ...find,
        }
      } else {
        const find = (this.options as Array<any>).find(
          (op) => op.value === value
        )
        valueSet[index] = {
          ...valueSet[index],
          ...find,
        }
      }
    }
    this.innerValue = valueSet
    setTimeout(() => {
      this.$emit('input', valueSet)
      this.$emit('change', valueSet)
      this.$forceUpdate()
    }, 10)
  }

  /** 判断是否显示步进 */
  checkIfShowStep(index: number) {
    if (this.checkIsGraphOptions(this.options)) {
      const isNodeNumber = ((this.options || {}) as any).nodeColumns?.find(
        (n: any) => n.value === this.value[index].value
      )?.isNumber
      const isLinkNumber = ((this.options || {}) as any).linkColumns?.find(
        (n: any) => n.value === this.value[index].value
      )?.isNumber
      return isNodeNumber || isLinkNumber
    }
    return ((this.options as Array<any>) || []).find(
      (item) => item.value === this.value[index].value
    )?.isNumber
  }
}
</script>
<style lang="less" scoped>
.comp-filter-column-selector {
  display: flex;
  flex-flow: row wrap;
  width: 100%;

  &.vertial {
    flex-flow: column nowrap;
  }

  .selet-item-box {
    width: 100%;

    &:last-child {
      margin-bottom: 8px;
    }
  }

  .number-step-box {
    align-items: center;
    color: #5d637e;
    display: flex;
    flex-flow: row nowrap;
    font-size: 12px;
    height: 32px;
    justify-content: flex-start;
    margin-top: 4px;
    width: 100%;

    .step {
      margin: 0 8px;
      width: 54px;

      /deep/ .ant-input-number-handler-wrap {
        display: none;
      }
    }
  }

  .select-item {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    width: 100%;

    &.fix {
      margin-bottom: 0;
    }

    &:first-child {
      margin-top: 8px;
    }

    &:last-child {
      margin-bottom: 0;
    }
  }

  .btn {
    border: 1px solid #eaeaea;
    color: #555;
    cursor: pointer;
    font-size: 13px;
    height: 24px;
    line-height: 24px;
    margin-left: 4px;
    padding: 0 2px;

    &:hover {
      border-color: #5760e6;
      color: #5760e6;
    }

    &.disabled {
      border-color: #eaeaea;
      color: #888;
      cursor: not-allowed;

      &:hover {
        border-color: #eaeaea;
        color: #888;
      }
    }

    &.sort-box {
      border-color: transparent;
      padding: 0;
      width: 16px;

      &:hover {
        border-color: transparent;
        color: #888;
      }
    }

    &.btn-func {
      position: relative;
    }

    .sort-item {
      border: 1px solid #eaeaea;
      color: #888;
      display: inline-block;
      float: left;
      font-size: 10px;
      height: 10px;
      line-height: 10px;
      width: 16px;
      width: 100%;

      &.active {
        color: #333;
      }

      &:hover {
        border-color: #5760e6;
        color: #5760e6;
      }

      &.disabled {
        cursor: not-allowed !important;

        &.active {
          color: #888;
        }

        &:hover {
          border: 1px solid #eaeaea;
          color: #888;
        }
      }

      &:first-child {
        margin-bottom: 2px;
      }
    }
  }
}

.vis-option {
  display: block;
  height: 32px;
  width: 100%;

  &.disabled {
    cursor: not-allowed;
    opacity: 0.5;
  }
}

/deep/ .ant-dropdown-menu-item.active {
  background: rgba(#5760e6, 0.15);
}
</style>
